package com.example.demo1.service;

import com.example.demo1.smconfig.TurnstileEvents;
import com.example.demo1.smconfig.TurnstileStates;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.util.UUID;

@Service
public class TurnstileStateMachineService {

    @Autowired
    private StateMachine<TurnstileStates, TurnstileEvents> stateMachine;


    /**
     * 在config 中配置直接自动启动， 不需要调用start 方法
     */
    public void init() {
        // stateMachine.start();
    }


    /**
     * 模拟支付、
     * 使用 MessageBuilder 构建事件消息对象
     * 新的API提供了更好的扩展性，支持在事件中携带额外的数据
     * 保持与Spring StateMachine最新版本的兼容性
     */
    public void doPay() {
        System.out.println("支付前状态: " + getCurrentState());
        System.out.println("收到了支付确认，状态机发送 COIN 事件, 切换状态");
        // 使用接收 Message 参数的 sendEvent 方法
        stateMachine.sendEvent(Mono.just(MessageBuilder.withPayload(TurnstileEvents.COIN).build()))
                .subscribe();
        System.out.println("支付后状态: " + getCurrentState());
    }
    /**
     * 模拟按键
     * 使用 MessageBuilder 构建事件消息对象
     * 新的API提供了更好的扩展性，支持在事件中携带额外的数据
     * 保持与Spring StateMachine最新版本的兼容性
     */
    public void doPush() {
        System.out.println("推门前状态: " + getCurrentState());
        System.out.println("模拟按键，状态机发送 PUSH 事件, 切换状态");
        /**
         * 状态机事件触发: 通过 stateMachine.sendEvent() 方法向状态机发送 PUSH 事件
         * 响应式编程: 使用 Mono.just() 包装事件消息，采用 Reactor 响应式编程模式
         * 事件构建: 通过 MessageBuilder.withPayload(TurnstileEvents.PUSH).build() 构建包含事件载荷的消息对象
         *
         * 事件封装: 将 TurnstileEvents.PUSH 事件封装成 Message 对象
         * 异步发送: 通过 Mono 将消息异步发送给状态机
         * 状态转换: 状态机接收到 PUSH 事件后，根据配置的状态转换规则进行状态变更
         * 订阅执行: 调用 .subscribe() 触发实际的事件发送操作
         */
        stateMachine.sendEvent(Mono.just(
                MessageBuilder.withPayload(TurnstileEvents.PUSH).build())
        ).subscribe();
        System.out.println("推门后状态: " + getCurrentState());
    }
    /**
     * 获取当前状态
     *
     * @return
     */
    public String getCurrentState() {
        return stateMachine.getState().getId().toString();
    }
}
